function Random(min, max) {
  return Math.random() * (max - min) + min;
}
class Color {
  constructor(r, g, b, a) {
    this.r = r;
    this.g = g;
    this.b = b;
    this.a = a;
  }
  val() {
    return `rgba(${this.r},${this.g},${this.b},${this.a})`;
  }
}
Color.random = function (isLimit = true) {
  let min = 0;
  let max = 255;
  let r = Math.floor(Random(min, max));
  let g = Math.floor(Random(min, max));
  let b = Math.floor(Random(min, max));
  return new Color(r, g, b, 0.8);
}

var Opacity_Step = 0.05;
var OPacity_Limit = 0.05;

class Point {
  constructor(x, y, radius, color) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;
    this.alive = true;
  }
  update() {
    if (!this.alive) {
      return;
    }
    if (this.color.a <= OPacity_Limit) {
      this.alive = false;
    }
    this.color.a -= Opacity_Step;
  }
  render(context) {
    context.fillStyle = this.color.val();
    context.beginPath();
    context.arc(this.x, this.y, this.radius, 0, Math.PI / 180 * 360);
    context.fill();
  }
}

class Particle {
  constructor(x, y, radius, color, vx, vy, gravity, duration) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;
    this.vx = vx;
    this.vy = vy;
    this.gravity = gravity;
    this.duration = duration;
    this.alive = true;
    this.points = [];
  }
  update() {
    this.duration -= 1;
    if (this.duration >= 0) {
      let c = new Color(this.color.r, this.color.g, this.color.b, this.color.a);
      let p = new Point(this.x, this.y, this.radius, c);
      this.points.push(p);
      this.x += this.vx;
      this.y += this.vy;
      this.vy += this.gravity;
    }
    this.points.forEach((e, i) => {
      if (!e.alive) {
        this.points.splice(i, 1);
      } else {
        e.update();
      }
    })
    if (this.points.length <= 0) {
      this.alive = false;
    }
  }
  render(context) {
    this.points.forEach((e, i) => {
      e.render(context);
    })
  }
}

class FireWorks {
  constructor(x, y, color, duration) {
    this.x = x;
    this.y = y;
    this.color = color;
    this.duration = duration;
    this.alive = true;
    this.ps = [];
    this.exploaded = false;
  }
  init() {
    let vx = Random(-7, 7);
    let vy = Random(-20,-15);
    // let vy = -15
    // let gravity = Random(0.05, 0.35);
    let gravity = 0.25;
    let lifeTime = Random(40, 120);
    this.main = new Particle(this.x, this.y, 6, this.color, vx, vy, gravity, lifeTime);
  }
  update() {
    if (this.main.alive) {
      this.main.update();
      this.x = this.main.x;
      this.y = this.main.y;
    }
    if(this.main.duration <= 0){
      if (!this.exploaded) {
        // 生成多个烟花粒子
        let count = Random(12,28);  
        // let count = 100;      
        let angle = 2 * Math.PI / count;
        let speed = 5;
        let time = Random(30,80);
        for (let i = 0; i < count; i++) {          
          let s = speed * Random(0.8,1);
          let r = Random(1,10);
          let vx = Math.cos(angle * r  * i) * s;
          let vy = Math.sin(angle * r * i) * s;      
          let p = new Particle(this.x, this.y, 3, this.color, vx, vy, 0.1, time);
          this.ps.push(p);
        }
        this.exploaded = true;
      }
    }
    if (this.ps.length != 0) {
      this.ps.forEach((e, i) => {
        if (!e.alive) {
          this.ps.splice(i, 1);
        }
        e.update();
      })
      if(this.ps.length == 0){
        this.alive = false;
      }
    }
  }
  render(context) {
    if (this.main.alive) {
      this.main.render(context)
    }
    if (this.ps.length != 0) {
      this.ps.forEach((e) => {
        e.render(context);
      })
    }
  }
}

(function () {
  let cvs = document.getElementById('cvs');
  let ww = document.body.clientWidth;
  let wh = document.body.clientHeight;
  cvs.width = ww;
  cvs.height = wh;
  window.onresize = function () {
    ww = document.body.clientWidth;
    wh = document.body.clientHeight;
    cvs.width = ww;
    cvs.height = wh;
  }
  let context = cvs.getContext('2d');

  let lock = Random(300,1400);
  let fs = [];

  function loop() {
    context.clearRect(0, 0, ww, wh);
    lock -= 15;
    if(lock <= 0){
      lock = Random(500,2000);
      let count = Math.floor(Random(1,6));
      for(let i =0; i < count;i++){
        let f = new FireWorks(ww * Random(0.3,0.7),wh,Color.random(),Random(30,60));
        fs.push(f);
        f.init();
      }
      
    }
    if(fs.length >0){
      fs.forEach((e,i)=>{
        if(e.alive){
          e.update();
          e.render(context);
        }else {
          fs.splice(i,1);
        }
      })
    }
    requestAnimationFrame(loop);
  }
  loop();
})();